<template>
  <div
    style="display: flex; flex-direction: column; height: calc(100vh - 130px)"
    @dragenter="handleDragEnter"
    @dragover="handleDragOver"
    v-loading="editLoading"
  >
    <div class="drag-upload" v-show="isShowDragUpload">
      <el-upload
        :drag="true"
        :multiple="true"
        v-model:file-list="fileList"
        :http-request="uploadRequest"
        :before-upload="beforeUpload"
        style="height: 100%; width: 100%"
      >
        <span class="drag-upload-message">拖动文字到此区域</span>
      </el-upload>
      <el-button class="drag-upload-close-button" @click="handleCloseDragUpload" link>
        <Icon icon="ic:baseline-close" :size="25" color="red" />
      </el-button>
    </div>
    <div style="display: flex">
      <el-button
        style="
          background-color: #7bbb63;
          height: 35px;
          color: white;
          border-radius: 3px 0px 0px 3px;
        "
        @click="handleSendMail"
      >
        <Icon icon="tabler:send" />
        发送
      </el-button>
      <el-dropdown @command="handleDelaySendCommand">
        <span class="el-dropdown-link">
          <Icon icon="solar:alt-arrow-down-bold" class="ml-1" />
        </span>
        <template #dropdown>
          <el-dropdown-menu>
            <el-dropdown-item command="scheduled">定时发送</el-dropdown-item>
            <el-dropdown-item command="delay">延时发送</el-dropdown-item>
          </el-dropdown-menu>
        </template>
      </el-dropdown>
      <el-button style="height: 35px; color: white" type="warning" @click="handleApproveMail">
        主动请审
      </el-button>
      <el-button style="height: 35px" @click="handleSaveMail">保存</el-button>
      <div style="margin-left: 10px; margin-top: 6px; font-size: 11pt" v-if="autoSaveLoading == 1">
        <Icon
          icon="material-symbols-light:check-circle"
          style="color: #91d279"
          class="align-middle"
        />
        <span>{{ saveMessage }}</span>
      </div>
      <div style="margin-left: 10px; margin-top: 6px" v-if="autoSaveLoading == 2">
        <Icon icon="svg-spinners:bars-rotate-fade" class="align-middle" style="margin-right: 3px" />
        <span>自动保存中...</span>
      </div>
      <div style="margin-left: auto">
        <span class="mail-info-span">发件人：</span>
        <el-select v-model="mailInfo.accountId" lable="发件人" @change="handleAccountIdChange">
          <el-option
            v-for="account in mailAccounts"
            :key="account.id"
            :label="account.mailboxAccount"
            :value="account.id"
          />
        </el-select>
      </div>
    </div>
    <div class="mail-info">
      <div>
        <span style="margin-left: 10px; min-width: 70px" class="mail-info-span"> 收件人： </span>
        <MailReceiver v-model="mailInfo.receivers" style="flex-grow: 1; margin-right: 20px" />
      </div>
      <div>
        <el-button link @click="handleClickShowBlindReceiver">
          <Icon
            :icon="isShowBlindReceiver ? 'solar:alt-arrow-down-bold' : 'solar:alt-arrow-right-bold'"
          />
        </el-button>
        <span style="min-width: 54px" class="mail-info-span">抄送： </span>
        <MailReceiver v-model="mailInfo.carbonReceivers" style="flex-grow: 1; margin-right: 20px" />
      </div>
      <div v-if="isShowBlindReceiver">
        <span style="margin-left: 25px; min-width: 54px" class="mail-info-span"> 密送： </span>
        <MailReceiver v-model="mailInfo.blindReceivers" style="flex-grow: 1; margin-right: 20px" />
      </div>
      <div>
        <span style="margin-left: 25px; min-width: 54px" class="mail-info-span"> 主题： </span>
        <el-input
          v-model="mailInfo.subject"
          style="flex-grow: 1; margin-right: 20px"
          class="subject-input"
        />
      </div>
    </div>
    <UploadFile v-model="fileList" :show-file-list="false" :is-show-tip="false" :fileSize="32">
      <el-button><Icon icon="mdi:paperclip" />附件</el-button>
    </UploadFile>

    <FileList v-model="fileList">
      <template #menu="{ item }">
        <context-menu-item label="删除" @click="handleDeleteResource(item)" />
        <context-menu-item label="重命名" @click="handleRenameResource(item)" />
        <context-menu-item label="复制附件名" @click="handleCopyResourceName(item)" />
      </template>
    </FileList>
    <div style="flex: 1">
      <Editor :height="editorHeight" v-model="mailInfo.content.content" @keydown="handleKeyDown" />
    </div>
  </div>
  <RenameFile ref="renameFileRef" @success="saveResourceName" />
  <MailDelayTimeSelect ref="delayTimeSelectRef" @success="saveDelayMail" />
</template>
<script setup lang="ts" name="MailEdit">
import MailReceiver from './MailReceiver.vue'
import { Editor } from '@/components/Editor'
import * as MailUtil from '@/views/mailbox/mail/MailUtil'
import type { UploadProps, UploadUserFile, UploadRawFile } from 'element-plus'
import { ElMessageBox } from 'element-plus'
import * as mailboxAccountApi from '@/api/mailbox/mailboxAccount'
import { cloneDeep } from '@pureadmin/utils'
import * as mailApi from '@/api/mailbox/mail'
import * as FileApi from '@/api/infra/file'
import * as signatureApi from '@/api/mailbox/mailSignature'
import { MailboxMailResourceTypeEnum } from '@/utils/constants'
import { isEmail } from '@pureadmin/utils'
import { useTagsViewStore } from '@/store/modules/tagsView'
import UploadFile from '@/components/UploadFile/src/UploadFile.vue'
import RenameFile from '@/components/UploadFile/src/RenameFile.vue'
import FileList from '@/components/UploadFile/src/FileList.vue'
import { formatDate } from '@/utils/formatTime'
import dayjs from 'dayjs'
import MailDelayTimeSelect from './MailDelayTimeSelect.vue'
import { useUserStore } from '@/store/modules/user'
const userStore = useUserStore()
const signatrueTypeEnum = {
  //新建
  NEW: 0,
  //回复
  REPLY: 1
}

const renameFileRef = ref()
const delayTimeSelectRef = ref()
const { currentRoute, push } = useRouter()
const tagsViewStore = useTagsViewStore()
const editLoading = ref(false)
const message = useMessage() // 消息弹窗
let hideDragUploadTimer: any = null

const isShowBlindReceiver = ref(false)
const isShowDragUpload = ref(false)
const editorHeight = ref('calc(100vh - 400px)')
const mailInfo = ref({
  id: 0,
  accountId: undefined,
  subject: '',
  isScheduled: false,
  planSendTime: undefined,
  receivers: [] as any[],
  carbonReceivers: [] as any[],
  blindReceivers: [] as any[],
  resources: [] as any[],
  content: { content: '' }
})

const fileList = ref<UploadUserFile[]>([])

const mailAccounts = ref<any[]>([])

const autoSaveLoading = ref(0)

const saveMessage = ref('')

const lastSaveTime = ref<Date>()

let intervalSaveId: any = null

const oldAccountId = ref<any>(0)

const ownerUserId = ref(0)

onMounted(async () => {
  ownerUserId.value = userStore.getUser.id
  await getMailAccounts()
  await initWriteMail()
  intervalSaveId = setInterval(handleAutoSaveTimer, 60000) // 每60秒触发一次
  window.addEventListener('keydown', handleKeyDown)
})

const getMailAccounts = async () => {
  // 获取邮箱账号
  if (mailAccounts.value.length > 0) return
  mailAccounts.value = await mailboxAccountApi.getTopAccount(ownerUserId.value)
  if (mailInfo.value.accountId == undefined) {
    mailInfo.value.accountId = mailAccounts.value[0].id
  }
}

const uploadRequest = async (options) => {
  const res = await FileApi.uploadFile({
    file: options.file
  })

  fileList.value.forEach((file) => {
    if (file.name == options.file.name) {
      file.url = res.data
    }
  })
}

const mailIsEmpty = () => {
  if (
    mailInfo.value.id == 0 &&
    mailInfo.value.subject == '' &&
    mailInfo.value.receivers.length == 0 &&
    mailInfo.value.carbonReceivers.length == 0 &&
    mailInfo.value.blindReceivers.length == 0 &&
    mailInfo.value.content.content == ''
  )
    return true
  else return false
}

const handleAutoSaveTimer = async () => {
  if (mailIsEmpty()) return
  const now = new Date()
  if (lastSaveTime.value == undefined || dayjs(now).diff(dayjs(lastSaveTime.value), 'second') < 30)
    return
  autoSaveLoading.value = 2
  try {
    await saveMail(1)
    updateSaveTime(0)
  } finally {
    autoSaveLoading.value = 1
  }
}

onBeforeUnmount(() => {
  clearInterval(intervalSaveId) // 清除定时器
  window.removeEventListener('keydown', handleKeyDown)
})

const handleKeyDown = async (event) => {
  if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 's') {
    // 阻止默认的保存对话框
    event.preventDefault()

    autoSaveLoading.value = 2
    try {
      await saveMail(1)
      message.success('保存成功')
      updateSaveTime(1)
    } finally {
      autoSaveLoading.value = 1
    }
  }
}

const updateSaveTime = (saveType) => {
  lastSaveTime.value = new Date()
  saveMessage.value =
    formatDate(lastSaveTime.value, 'HH:mm:ss') + (saveType == 0 ? '自动' : '手动') + '保存成功'
}

onActivated(async () => {
  editLoading.value = true
  try {
    if (history.state.accountId != undefined && history.state.accountId != 0) {
      mailInfo.value.accountId = cloneDeep(history.state.accountId)
      delete history.state.accountId
    }

    if (history.state.userId != undefined && history.state.userId != 0) {
      ownerUserId.value = history.state.userId
      delete history.state.userId
    }

    if (mailInfo.value.accountId == undefined) {
      await getMailAccounts()
    }
    const srcMailId = history.state.mailId != undefined ? history.state.mailId : 0
    delete history.state.mailId
    if (history.state.type != undefined) {
      switch (history.state.type) {
        case 'editAgain':
          await initWriteAgainMail(srcMailId)
          break
        case 'reply':
          await initReplyMail(srcMailId)
          break
        case 'replyAll':
          await initRlyAllMail(srcMailId)
          break
        case 'forwad':
          await initForwadMail(srcMailId)
          break
        case 'forwadAsAttachment':
          await initForwadAsAttachment(srcMailId)
          break
        case 'customerSend':
          await initCustomerWriteMail(history.state.receivers, history.state.carbonReceivers)
          break
        case 'write':
          await initWriteMail()
          break
      }
      delete history.state.type
    }
  } finally {
    editLoading.value = false
  }
})

const getAccountSignature = async (type) => {
  const content = await signatureApi.singleGetAccountSignature({
    accountId: mailInfo.value.accountId,
    type: type
  })
  return content
}

const calcRelyContent = async (srcMailInfo) => {
  const signatureContent = await getAccountSignature(signatrueTypeEnum.REPLY)
  return (
    '<div style="margin: 0;">&nbsp;</div>' +
    '<div style="margin: 0;">&nbsp;</div>' +
    signatureContent +
    (signatureContent ? '<div style="margin: 0;">&nbsp;</div>' : '') +
    MailUtil.getReplyContent(srcMailInfo) +
    srcMailInfo.content.content
  )
}

const initCustomerWriteMail = async (receivers, carbonReceivers) => {
  await initWriteMail()

  if (receivers != undefined) mailInfo.value.receivers = receivers
  if (carbonReceivers != undefined) mailInfo.value.carbonReceivers = carbonReceivers
}

const initWriteMail = async () => {
  const signatureContent = await getAccountSignature(signatrueTypeEnum.NEW)
  if (signatureContent) {
    mailInfo.value.content.content =
      '<div style="margin: 0;">&nbsp;</div>' +
      '<div style="margin: 0;">&nbsp;</div>' +
      signatureContent
  }
  oldAccountId.value = mailInfo.value.accountId
}

const initWriteAgainMail = async (srcMailId) => {
  let srcMailInfo = await getSrcMailInfo(srcMailId)
  mailInfo.value = srcMailInfo
  initAttachment()
}

const initReplyMail = async (srcMailId) => {
  let srcMailInfo = await getSrcMailInfo(srcMailId)
  srcMailInfo.content.content = await calcRelyContent(srcMailInfo)
  srcMailInfo.receivers = srcMailInfo.froms
  srcMailInfo.carbonReceivers = []
  mailInfo.value = srcMailInfo
  initAttachment()
}

const initRlyAllMail = async (srcMailId) => {
  let srcMailInfo = await getSrcMailInfo(srcMailId)
  srcMailInfo.content.content = await calcRelyContent(srcMailInfo)

  srcMailInfo.receivers = [...srcMailInfo.froms, ...srcMailInfo.receivers]

  const currentAccountAddress = mailAccounts.value.find(
    (account) => (account.id = mailInfo.value.accountId)
  ).mailboxAccount
  // 将当前发件人从收件人中剔除
  srcMailInfo.receivers = srcMailInfo.receivers.filter((receiver) => {
    if (receiver.address == currentAccountAddress) return false
    else return true
  })
  // 将当前发件人从抄送人中剔除
  srcMailInfo.carbonReceivers = srcMailInfo.carbonReceivers.filter((carbonReceiver) => {
    if (carbonReceiver.address == currentAccountAddress) return false
    else return true
  })
  mailInfo.value = srcMailInfo
  initAttachment()
}

const initForwadMail = async (srcMailId) => {
  let srcMailInfo = await getSrcMailInfo(srcMailId)
  srcMailInfo.content.content = await calcRelyContent(srcMailInfo)
  srcMailInfo.receivers = []
  srcMailInfo.carbonReceivers = []
  mailInfo.value = srcMailInfo
  initAttachment()
}

const initAttachment = () => {
  mailInfo.value.resources.forEach((resource) => {
    if (resource.resourceType == MailboxMailResourceTypeEnum.ATTACHMENT)
      fileList.value.push({
        name: resource.fileName,
        url: resource.urlName,
        size: resource.size
      })
  })
}

const initForwadAsAttachment = async (srcMailId) => {
  let srcMailInfo = await getSrcMailInfo(srcMailId)
  const mailAttachment = await mailApi.saveMailAsFile(srcMailId)

  mailInfo.value.subject = srcMailInfo.subject
  fileList.value.push({
    name: mailAttachment.fileName,
    url: mailAttachment.urlName,
    size: mailAttachment.size
  })
}

const getSrcMailInfo = async (srcMailId) => {
  let srcMailInfo = await mailApi.getMailDetail(srcMailId)
  srcMailInfo.id = 0

  srcMailInfo.blindReceivers = []

  return srcMailInfo
}

const handleDeleteResource = (item) => {
  fileList.value = fileList.value.filter((resourceItem) => {
    if (resourceItem == item) return false
    else return true
  })
}

const handleRenameResource = (item) => {
  const index = fileList.value.indexOf(item)
  renameFileRef.value.open(index, item.name)
}

const handleCopyResourceName = async (item) => {
  await navigator.clipboard.writeText(item.name)
}

const saveResourceName = (index, name) => {
  fileList.value[index].name = name
}

const handleClickShowBlindReceiver = () => {
  isShowBlindReceiver.value = !isShowBlindReceiver.value
  if (isShowBlindReceiver.value) {
    editorHeight.value = 'calc(100vh - 440px)'
  } else {
    editorHeight.value = 'calc(100vh - 400px)'
  }
}

const judgeReceiverAddressLegal = async (receivers) => {
  let index = 0 // 用于跟踪当前处理的索引
  while (index < receivers.length) {
    if (isEmail(receivers[index].address)) {
      index++
      continue
    }
    try {
      // 等待用户确认
      const result = await ElMessageBox.confirm(
        '"' + receivers[index].address + '"是一个无效的Email地址,是否忽略这个地址?',
        '警告',
        {
          confirmButtonText: '是',
          cancelButtonText: '否',
          type: 'warning'
        }
      )
      if (result === 'confirm') {
        receivers.splice(index, 1)
      } else {
        index++
      }
    } catch (error) {
      return false
    }
  }

  return true
}

const judgeReceiverLegal = async () => {
  if (!(await judgeReceiverAddressLegal(mailInfo.value.receivers))) {
    return false
  }

  if (!(await judgeReceiverAddressLegal(mailInfo.value.carbonReceivers))) {
    return false
  }

  if (!(await judgeReceiverAddressLegal(mailInfo.value.blindReceivers))) {
    return false
  }
  if (
    mailInfo.value.receivers.length == 0 &&
    mailInfo.value.carbonReceivers.length == 0 &&
    mailInfo.value.blindReceivers.length == 0
  ) {
    message.alertError('请填写收件人')
    return false
  }

  return true
}

const handleSendMail = async () => {
  if (!(await judgeReceiverLegal())) return

  editLoading.value = true
  try {
    await saveMail(0)
    message.success('发送成功')
    closeCurrentPage()
  } finally {
    editLoading.value = false
  }
}

const handleApproveMail = async () => {
  if (!(await judgeReceiverLegal())) return

  editLoading.value = true
  try {
    await saveMail(2)
    message.success('保存成功')
    closeCurrentPage()
  } finally {
    editLoading.value = false
  }
}

const closeCurrentPage = () => {
  if (unref(currentRoute)?.meta?.affix) return
  tagsViewStore.delView(unref(currentRoute))
  const visitedViews = tagsViewStore.getVisitedViews
  const latestView = visitedViews.slice(-1)[0]
  if (latestView) {
    push(latestView)
  } else {
    push('/')
  }
}

const handleSaveMail = async () => {
  autoSaveLoading.value = 2
  try {
    await saveMail(1)
    updateSaveTime(1)
    message.success('保存成功')
  } finally {
    autoSaveLoading.value = 1
  }
}

const saveMail = async (type: number) => {
  if (mailIsEmpty()) return
  mailInfo.value.resources = []
  fileList.value.forEach((file) => {
    mailInfo.value.resources.push({
      fileName: file.name,
      urlName: file.url,
      resourceType: MailboxMailResourceTypeEnum.ATTACHMENT,
      size: file.size
    })
  })
  const mailId = await mailApi.saveMail(Object.assign(mailInfo.value, { type: type }))
  mailInfo.value.id = mailId
}

// 文件上传之前判断
const beforeUpload: UploadProps['beforeUpload'] = (file: UploadRawFile) => {
  const isLimit = file.size < 32 * 1024 * 1024
  if (!isLimit) {
    message.error(`上传文件大小不能超过32MB!`)
    return false
  }
  if (isShowDragUpload.value) isShowDragUpload.value = false
}

const handleDragEnter = (event) => {
  event.preventDefault()
  event.stopPropagation()

  if (!isShowDragUpload.value) isShowDragUpload.value = true
}

const handleDragOver = (event) => {
  event.preventDefault()
  event.stopPropagation()
  if (hideDragUploadTimer != null) clearTimeout(hideDragUploadTimer)
  hideDragUploadTimer = setTimeout(() => {
    isShowDragUpload.value = false
  }, 1000)
}

const handleCloseDragUpload = () => {
  if (isShowDragUpload.value) isShowDragUpload.value = false
}

const handleDelaySendCommand = async (command) => {
  if (!(await judgeReceiverLegal())) return
  delayTimeSelectRef.value.open(command)
}

const saveDelayMail = async (sendTime, type) => {
  mailInfo.value.isScheduled = true
  mailInfo.value.planSendTime = sendTime
  await saveMail(1)
  if (type == 'delay') message.success('延迟发送成功')
  else message.success('定时发送成功')
  closeCurrentPage()
}

const handleAccountIdChange = async (accountId) => {
  // 更新签名 将id设置为0
  mailInfo.value.id = 0
  let oldSinatureContent = undefined
  if (oldAccountId.value != accountId) {
    if (oldAccountId.value != 0) {
      oldSinatureContent = await signatureApi.singleGetAccountSignature({
        accountId: oldAccountId.value,
        type: signatrueTypeEnum.NEW
      })
    }

    const signatureContent = await signatureApi.singleGetAccountSignature({
      accountId: mailInfo.value.accountId,
      type: signatrueTypeEnum.NEW
    })
    if (oldSinatureContent && mailInfo.value.content.content.includes(oldSinatureContent)) {
      mailInfo.value.content.content = mailInfo.value.content.content.replace(
        oldSinatureContent,
        signatureContent
      )
    } else {
      mailInfo.value.content.content =
        '<div style="margin: 0;">&nbsp;</div>' +
        '<div style="margin: 0;">&nbsp;</div>' +
        signatureContent
    }
  }
  oldAccountId.value = accountId
}
</script>
<style scoped>
.mail-info {
  margin: 10px 0;
  padding-top: 10px;
  padding-bottom: 15px;
  border: 1px solid #cccccc;
}
.mail-info > div {
  width: 100%;
  margin-top: 5px;
  margin-left: 10px;
  display: flex;
}

.drag-upload {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: 2px dashed red;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  z-index: 1; /* 确保覆盖在 dropzone 之上 */
  background-color: rgba(255, 255, 255, 0.8);
  opacity: 0.5;
}

.drag-upload-close-button {
  position: absolute;
  top: 5px;
  right: 5px;
  background-color: white;
  padding: 5px 10px;
  cursor: pointer;
}

.drag-upload-message {
  font-size: 18px;
  color: #333;
}

.mail-info-span {
  margin-top: 5px;
  font-size: 11pt;
}
.subject-input :deep(.el-input__inner) {
  color: black;
}

.el-dropdown-link {
  cursor: pointer;
  color: white;
  display: flex;
  align-items: center;
  background-color: #7bbb63;
  height: 33px;
  width: 25px;
  border-radius: 0px 3px 3px 0px;
  margin-left: 0px;
  margin-top: 1px;
  margin-right: 8px;
}
.el-dropdown-link:focus-visible {
  outline: none !important;
}
</style>
